home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-25 | 15.8 KB | 639 lines | [TEXT/PJMM] |
- {This program was written by Eric Kilk in 1985, as a Desk Accessory. It was revived in 1995 by Ken Long,}
- {who turned it into an application. After he posted it to alt.sources.mac, I (Ingemar R), modified it to give it}
- {some functionality I found lacking. New features:}
- {}
- {• Updates automatically}
- {• Resizeable}
- {• More hour marks}
- {• Optional digits (3, 6, 9 and 12), roman or arabic}
- {• Black or white}
- {}
- {Do you feel like working some more on it? Colorize? Seconds? Circular WDEF? Put it in the menu bar?}
- {More options?}
- {}
- {- Fixes 21 of april:}
- {• Checked the "can background" flag so it updates when in the background}
- {• Modified the hands so they draw correctly}
- {}
- {- 25 of April:}
- {Ken Long released his C version of this code, which added a second hand (Second}
- {hand code? I guess so.) and I really can't let the Pascal version fall behind… so I}
- {added seconds here too - but made it optional. So:}
- {• A hand for seconds.}
- {• Incorporated Ken's BNDL and icons.}
- {• Thicker hands as an option.}
- {• Added a circular WDEF. (Source to that is not included at this time.)}
- {• Checked the "Get front clicks" flag as suggested by someone in a.s.m.}
- {• Added project and IFC's for MetroWerks Pascal.}
-
-
- program NewWatch;
-
- {$IFC UNDEFINED THINK_PASCAL}
- uses
- Types, QuickDraw, Events, Menus, Dialogs, Fonts, Resources, Devices;
- {$ENDC}
-
- const
- appleID = 1;
- fileID = 2;
- editID = 3;
- optionsID = 4;
-
- helpItem = 1;
- defaultItem = 2;
- quitItem = 4;
-
- kTwoPi = 6.2831;
-
- var
- appleMenu, fileMenu, editMenu, optionsMenu: MenuHandle;
-
- clockWindow, whatWindow: WindowPtr;
- dragRect: Rect;
-
- type
- settingsType = packed record
- display: Integer;
- black: Boolean;
- seconds: Boolean;
- fancy: Boolean;
- end;
- var
- settings: SettingsType;
-
- gDone, gHasWNE, gColorQDFlag, g32bQDFlag: Boolean;
- gPrevDateTime: DateTimeRec;
-
- type
- WindowTemplate = record
- boundsRect: Rect;
- procID: Integer;
- visible: Boolean;
- filler1: Boolean;
- goAwayFlag: Boolean;
- filler2: Boolean;
- refCon: LongInt;
- title: Str255;
- end;
- WindowTPtr = ^WindowTemplate;
- WindowTHnd = ^WindowTPtr;
- var
- wt: WindowTHnd;
-
-
-
- procedure EK;
- begin
- Move(-3, 0);
- Line(0, 4);
- Move(1, -4);
- Line(1, 0);
- Move(-1, 2);
- Line(0, 0);
- Move(0, 2);
- Line(1, 0);
- Move(2, -4);
- Line(0, 4);
- Move(1, -2);
- Line(2, -2);
- Move(-1, 3);
- Line(1, 1);
- end; {EK}
-
- procedure DrawHands (dateTime: DateTimeRec);
- var
- mx, my, hx, hy, sx, sy: Integer; {• hand end-points */}
- m1x, m1y, m2x, m2y: Integer;
- h1x, h1y, h2x, h2y: Integer;
- r: Rect;
- minUnit, min, hr, sec, secUnit: Double; {• time */}
- cxSize, cySize: Integer;
- hourRgn, minuteRgn, secRgn: RgnHandle;
- const
- kSecondLength = 0.8;
- kMinuteLength = 0.75;
- kHourLength = 0.5;
- kMinuteSpecial = 0.55;
- kHourSpecial = 0.4;
- kMinuteWidth = 0.07;
- kHourWidth = 0.10;
-
- function Sgn (arg: Integer): Integer;
- begin
- if arg > 0 then
- Sgn := 1
- else if arg < 0 then
- Sgn := -1
- else
- Sgn := 0;
- end; {Sgn}
-
- begin
- SetPort(clockWindow);
- cxSize := (clockWindow^.portRect.right - clockWindow^.portRect.left) div 2;
- cySize := (clockWindow^.portRect.bottom - clockWindow^.portRect.top) div 2;
- SetOrigin(-cxSize, -cySize); {• make 0,0 in center */}
-
- minUnit := dateTime.minute / 60.0;
- min := minUnit * kTwoPi; {• 2*pi */}
- hr := (dateTime.hour + minUnit) / 12.0 * kTwoPi;
- mx := Trunc(kMinuteLength * cxSize * sin(min));
- my := Trunc(-kMinuteLength * cySize * cos(min));
- if settings.fancy then {Fancy hands}
- begin
- m1x := Trunc(kMinuteSpecial * cxSize * sin(min + kMinuteWidth));
- m1y := Trunc(-kMinuteSpecial * cySize * cos(min + kMinuteWidth));
- m2x := Trunc(kMinuteSpecial * cxSize * sin(min - kMinuteWidth));
- m2y := Trunc(-kMinuteSpecial * cySize * cos(min - kMinuteWidth));
- end;
- hx := Trunc(kHourLength * cxSize * sin(hr));
- hy := Trunc(-kHourLength * cySize * cos(hr));
- if settings.fancy then {Fancy hands}
- begin
- h1x := Trunc(kHourSpecial * cxSize * sin(hr + kHourWidth));
- h1y := Trunc(-kHourSpecial * cySize * cos(hr + kHourWidth));
- h2x := Trunc(kHourSpecial * cxSize * sin(hr - kHourWidth));
- h2y := Trunc(-kHourSpecial * cySize * cos(hr - kHourWidth));
- end;
-
- {Additions for seconds:}
- if settings.seconds then
- begin
- secUnit := dateTime.second / 60.0;
- sec := secUnit * kTwoPi;
- sx := Trunc(kSecondLength * cxSize * sin(sec));
- sy := Trunc(-kSecondLength * cySize * cos(sec));
- end;
-
- hourRgn := NewRgn;
- minuteRgn := NewRgn;
- secRgn := NewRgn;
-
- if settings.seconds then
- begin
- OpenRgn;
- MoveTo(0, 0); {• create the seconds hand region}
- LineTo(sx, sy);
- if abs(sx) > abs(sy) then
- Line(0, Sgn(sx))
- else
- Line(-Sgn(sy), 0);
- Line(-sx, -sy);
- LineTo(0, 0);
- CloseRgn(secRgn);
- end;
-
- OpenRgn;
- MoveTo(0, 0); {• create the minute hand region}
- if settings.fancy then
- LineTo(m2x, m2y);
- LineTo(mx, my);
- if abs(mx) > abs(my) then
- Line(0, Sgn(mx))
- else
- Line(-Sgn(my), 0);
- if settings.fancy then
- begin
- Line(m1x - mx, m1y - my);
- Line(-m1x, -m1y);
- end
- else
- Line(-mx, -my);
- LineTo(0, 0);
- CloseRgn(minuteRgn);
-
- OpenRgn;
- MoveTo(0, 0); {• create the hour hand region}
- if settings.fancy then
- LineTo(h2x, h2y);
- LineTo(hx, hy);
- if abs(hx) > abs(hy) then
- Line(0, Sgn(hx))
- else
- Line(-Sgn(hy), 0);
- if settings.fancy then
- begin
- Line(h1x - hx, h1y - hy);
- Line(-h1x, -h1y);
- end
- else
- Line(-hx, -hy);
- LineTo(0, 0);
- CloseRgn(hourRgn);
-
- UnionRgn(hourRgn, minuteRgn, minuteRgn);
- if settings.seconds then
- UnionRgn(secRgn, minuteRgn, minuteRgn);
-
- PaintRgn(minuteRgn); {• draw the hands.}
- DisposeRgn(minuteRgn);
- DisposeRgn(hourRgn);
- DisposeRgn(secRgn);
-
- {MoveTo(0, 0); {• erase the center dot.}
- {PenPat(white);}
- {LineTo(0, 0);}
- {PenPat(black);}
- end; {DrawHands}
-
- procedure ShowClock;
- {• draw the entire clock face */}
- var
- dateTime: DateTimeRec; {• date gets read into here */}
-
- cxSize, cySize: Integer;
-
- fInfo: FontInfo;
- theTextSize: Integer;
- begin
- SetPort(clockWindow);
- PenNormal;
- if settings.black then
- PaintRect(clockWindow^.portRect)
- else
- EraseRect(clockWindow^.portRect);
-
- cxSize := (clockWindow^.portRect.right - clockWindow^.portRect.left) div 2;
- cySize := (clockWindow^.portRect.bottom - clockWindow^.portRect.top) div 2;
-
- GetTime(dateTime);
- if (dateTime.hour > 11) then
- dateTime.hour := dateTime.hour - 12;
- SetOrigin(-cxSize, -cySize); {• make 0,0 in center */}
- PenMode(srcXor);
-
- {The text size is determined from the smallest side!}
- if cxSize > cySize then
- theTextSize := cySize div 5
- else
- theTextSize := cxSize div 5;
-
- TextSize(theTextSize);
- GetFontInfo(fInfo);
-
- if (settings.display = 0) or (theTextSize < 6) then
- begin
- MoveTo(0, cySize - 2);
- Line(0, 0); {• draw 4 ticks.}
- MoveTo(cxSize - 2, 0);
- Line(0, 0);
- MoveTo(0, -cySize + 1);
- Line(0, 0);
- MoveTo(-cxSize + 1, 0);
- Line(0, 0);
- end
- else if settings.display = 1 then
- begin
- PenMode(patXor);
- if settings.black then
- ForeColor(whiteColor);
- MoveTo(0 - StringWidth('6') div 2, cySize - 2);
- DrawString('6');
- MoveTo(cxSize - 0 - StringWidth('3'), 0 + fInfo.ascent div 2);
- DrawString('3');
- MoveTo(0 - StringWidth('12') div 2, -cySize + 0 + fInfo.ascent);
- DrawString('12');
- MoveTo(-cxSize + 1, 0 + fInfo.ascent div 2);
- DrawString('9');
- ForeColor(blackColor);
- end
- else
- begin
- if settings.black then
- ForeColor(whiteColor);
- PenMode(patXor);
- MoveTo(0 - StringWidth('VI') div 2, cySize - 2);
- DrawString('VI');
- MoveTo(cxSize - 0 - StringWidth('III'), 0 + fInfo.ascent div 2);
- DrawString('III');
- MoveTo(0 - StringWidth('XII') div 2, -cySize + 0 + fInfo.ascent);
- DrawString('XII');
- MoveTo(-cxSize + 1, 0 + fInfo.ascent div 2);
- DrawString('IX');
- ForeColor(blackColor);
- end;
-
- {Draw the rest of the marks}
- MoveTo(Trunc((cxSize - 2) * 0.866), Trunc((cySize - 2) * 0.5));
- Line(0, 0);
- MoveTo(Trunc((cxSize - 2) * 0.5), Trunc((cySize - 2) * 0.866));
- Line(0, 0);
- MoveTo(-Trunc((cxSize - 2) * 0.866), Trunc((cySize - 2) * 0.5));
- Line(0, 0);
- MoveTo(-Trunc((cxSize - 2) * 0.5), Trunc((cySize - 2) * 0.866));
- Line(0, 0);
- MoveTo(Trunc((cxSize - 2) * 0.866), -Trunc((cySize - 2) * 0.5));
- Line(0, 0);
- MoveTo(Trunc((cxSize - 2) * 0.5), -Trunc((cySize - 2) * 0.866));
- Line(0, 0);
- MoveTo(-Trunc((cxSize - 2) * 0.866), -Trunc((cySize - 2) * 0.5));
- Line(0, 0);
- MoveTo(-Trunc((cxSize - 2) * 0.5), -Trunc((cySize - 2) * 0.866));
- Line(0, 0);
-
- {Draw EK}
- MoveTo(0, cySize div 2); {5}
- EK;
-
- DrawHands(dateTime);
-
- gPrevDateTime := dateTime;
- end; {ShowClock}
-
- procedure BackgroundTask;
- var
- dateTime: DateTimeRec; {• date gets read into here */}
- begin
- GetTime(dateTime);
- if (dateTime.minute <> gPrevDateTime.minute) or (settings.seconds and (dateTime.second <> gPrevDateTime.second)) then
- begin
- SetPort(clockWindow);
- PenMode(srcXor);
- DrawHands(gPrevDateTime);
- PenMode(srcXor);
- DrawHands(dateTime);
- gPrevDateTime := dateTime;
- end;
- end; {BackgroundTask}
-
- procedure SetUpWindow;
- var
- wr: Rect;
- begin
- {$IFC UNDEFINED THINK_PASCAL}
- dragRect := qd.screenBits.bounds;
- {$ELSEC}
- dragRect := screenBits.bounds;
- {$ENDC}
-
- {Color doesn't matter yet, but why not prepare for it?}
- if gColorQDFlag then
- clockWindow := GetNewCWindow(128, nil, WindowPtr(-1))
- else
- clockWindow := GetNewWindow(128, nil, WindowPtr(-1));
- SetPort(clockWindow);
- end; {SetUpWindow}
-
- procedure SetUpMenus;
- begin
- appleMenu := NewMenu(appleID, stringof(char($14)));
- InsertMenu(appleMenu, 0);
- fileMenu := NewMenu(fileID, 'File');
- InsertMenu(fileMenu, 0);
- editMenu := NewMenu(editID, 'Edit');
- InsertMenu(editMenu, 0);
- optionsMenu := NewMenu(optionsID, 'Options');
- InsertMenu(optionsMenu, 0);
- AppendMenu(appleMenu, 'About NewWatch…');
- {$IFC UNDEFINED THINK_PASCAL}
- AppendResMenu(appleMenu, 'DRVR');
- {$ELSEC}
- AddResMenu(appleMenu, 'DRVR');
- {$ENDC}
- AppendMenu(fileMenu, 'Help/H;Standard size/N;(-;Quit/Q');
- AppendMenu(editMenu, 'Undo/Z;(-;Cut/X;Copy/C;Paste/V;Clear');
- AppendMenu(optionsMenu, 'White;Black;(-;Dots;Arabic;Roman;(-;Show seconds;Thick hands');
- DrawMenuBar;
- end; {SetUpMenus}
-
- procedure AdjustMenus;
- var
- wp: WindowPeek;
- kind: Integer;
- DA: Boolean;
- procedure Enable (menu: MenuHandle; item: Integer; ok: Boolean);
- begin
- if ok then
- EnableItem(menu, item)
- else
- DisableItem(menu, item);
- end; {Enable}
- begin
- wp := WindowPeek(FrontWindow);
- if wp = nil then
- kind := 0
- else
- kind := wp^.windowKind;
- DA := kind < 0;
-
- Enable(editMenu, 1, DA);
- Enable(editMenu, 3, DA);
- Enable(editMenu, 4, DA);
- Enable(editMenu, 5, DA);
- Enable(editMenu, 6, DA);
-
- CheckItem(optionsMenu, 1, not settings.black);
- CheckItem(optionsMenu, 2, settings.black);
-
- CheckItem(optionsMenu, 4, settings.display = 0);
- CheckItem(optionsMenu, 5, settings.display = 1);
- CheckItem(optionsMenu, 6, settings.display = 2);
-
- CheckItem(optionsMenu, 8, settings.seconds);
- CheckItem(optionsMenu, 9, settings.fancy);
- end; {AdjustMenus}
-
- procedure HandleMenu (mSelect: LongInt);
- var
- menuID: Integer;
- menuItem: Integer;
- name: Str255;
- savePort: GrafPtr;
- theFrontWindow: WindowPeek;
- begin
- menuID := HiWrd(mSelect);
- menuItem := LoWrd(mSelect);
-
- case menuID of
- appleID:
- if menuItem = 1 then
- begin
- if Alert(128, nil) = 1 then {About…}
- ;
- end
- else
- begin
- GetPort(savePort);
- {$IFC UNDEFINED THINK_PASCAL}
- GetMenuItemText(appleMenu, menuItem, name);
- {$ELSEC}
- GetItem(appleMenu, menuItem, name);
- {$ENDC}
- if OpenDeskAcc(name) = 0 then
- ;
- SetPort(savePort);
- end;
- fileID:
- case menuItem of
- helpItem:
- begin
- if Alert(129, nil) = 1 then {Show help text}
- ;
- end;
- defaultItem:
- begin
- SizeWindow(clockWindow, 32, 32, false);
- SetPort(clockWindow);
- InvalRect(clockWindow^.portRect);
- {Move it to some safe place too}
- MoveWindow(clockWindow, 40, 40, true);
- end;
- quitItem:
- gDone := true;
- end; {case}
- editID:
- if not SystemEdit(menuItem - 1) then
- SysBeep(5);
- optionsID:
- begin
- case menuItem of
- 1:
- settings.black := false;
- 2:
- settings.black := true;
- 8:
- settings.seconds := not settings.seconds;
- 9:
- settings.fancy := not settings.fancy;
- otherwise
- settings.display := menuItem - 4;
- end; {case}
- InvalRect(clockWindow^.portRect);
- AdjustMenus;
- end;
- end;
- end; {HandleMenu}
-
- procedure InitMacintosh;
- const
- _WaitNextEvent = $A860;
- _Unimplemented = $A89F;
- _GetCIcon = $AA1E; {E.g. any Color QuickDraw routine}
- k32bQD = $AB1D;
- begin
- {$IFC UNDEFINED THINK_PASCAL}
- MaxApplZone;
-
- InitGraf(@qd.thePort);
- InitFonts;
- FlushEvents(everyEvent, 0);
- InitWindows;
- InitMenus;
- TEInit;
- InitDialogs(nil);
- {$ENDC}
- InitCursor;
-
- gHasWNE := NGetTrapAddress(_WaitNextEvent, ToolTrap) <> NGetTrapAddress(_Unimplemented, ToolTrap);
- gColorQDFlag := NGetTrapAddress(_GetCIcon, ToolTrap) <> NGetTrapAddress(_Unimplemented, ToolTrap);
- g32bQDFlag := NGetTrapAddress(k32bQD, ToolTrap) <> NGetTrapAddress(_Unimplemented, ToolTrap);
- end;
-
- procedure HandleMouseDown (var theEvent: EventRecord);
- var
- theWindow: WindowPtr;
- windowCode: Integer;
- growResult: Longint;
- begin
- windowCode := FindWindow(theEvent.where, theWindow);
-
- case windowCode of
- inSysWindow:
- SystemClick(theEvent, theWindow);
- inMenuBar:
- begin
- AdjustMenus;
- HandleMenu(MenuSelect(theEvent.where));
- end;
- inDrag: {We should not have any, but just in case someone hacks it…}
- if theWindow = clockWindow then
- DragWindow(clockWindow, theEvent.where, dragRect);
- inContent:
- if theWindow = clockWindow then
- begin
- if theWindow <> FrontWindow then
- SelectWindow(clockWindow)
- else if BAnd(theEvent.modifiers, optionKey) <> 0 then {Option-klick = resize!}
- begin
- growResult := GrowWindow(clockWindow, theEvent.where, GetGrayRgn^^.rgnBBox);
- if growResult <> 0 then
- begin
- SizeWindow(clockWindow, LoWrd(growResult), HiWrd(growResult), false);
- SetPort(clockWindow);
- InvalRect(clockWindow^.portRect);
- end;
- end
- else
- DragWindow(clockWindow, theEvent.where, dragRect);
- end;
- { inGoAway: }
- { if (theWindow = clockWindow) then if TrackGoAway(clockWindow, theEvent.where) then}
- { gDone := true;}
- end;
- end;
-
- procedure HandleEvent;
- var
- ok: Boolean;
- theEvent: EventRecord;
- begin
- HiliteMenu(0);
-
- if gHasWNE then
- ok := WaitNextEvent(everyEvent, theEvent, 60, nil) {sleeptime of 1 second - we can't need more if we have a seconds hand!}
- else
- begin
- SystemTask; {• Handle desk accessories.}
- ok := GetNextEvent(everyEvent, theEvent);
- end;
-
- if ok then
- case theEvent.what of
- mouseDown:
- HandleMouseDown(theEvent);
- keyDown, autoKey:
- if BAnd(theEvent.modifiers, cmdKey) <> 0 then
- begin
- AdjustMenus;
- HandleMenu(MenuKey(char(BAnd(theEvent.message, charCodeMask))));
- end;
- updateEvt:
- begin
- {Because of the xor-based updates, I can't just update a part of the window, but must}
- {invalidate all of it!}
- SetPort(clockWindow);
- InvalRect(clockWindow^.portRect);
- {After that, a normal update!}
- BeginUpdate(clockWindow);
- ShowClock;
- EndUpdate(clockWindow);
- end;
- activateEvt:
- InvalRect(clockWindow^.portRect);
- end
- else
- BackgroundTask;
- end; {HandleEvent}
-
- { main program }
- begin
- InitMacintosh;
- SetUpMenus;
- SetUpWindow;
- settings := SettingsType(GetWRefCon(clockWindow));
- ShowClock;
-
- while not gDone do
- HandleEvent;
-
- SetPort(clockWindow);
-
- wt := WindowTHnd(GetResource('WIND', 128));
- wt^^.boundsRect := clockWindow^.portRect;
- LocalToGlobal(wt^^.boundsRect.topLeft);
- LocalToGlobal(wt^^.boundsRect.botRight);
- wt^^.refCon := Longint(settings);
- ChangedResource(Handle(wt));
-
- end.